import { isEmpty } from 'lodash'
import { useRequest } from 'ahooks'
import { Icon } from '@taroify/icons'
import { ScrollView, Text, View } from '@tarojs/components'
import { Cell, Empty, Loading, Navbar, Popup, SafeArea } from '@taroify/core'
import { useCallback, useEffect, useMemo, useState, type FC, type ReactNode } from 'react'

export interface PopupSelectProps {
  className?: string
  data?: Data[]
  open?: boolean
  title?: ReactNode
  params?: API.Req
  labelKey?: string
  valueKey?: string
  briefClass?: string
  labelClass?: string
  emptyText?: ReactNode
  emptyExtra?: ReactNode
  cancelText?: ReactNode
  confirmText?: ReactNode
  request?: Service
  transform?: (data: any) => Data[]
  formatter?: (item: Data, index: number) => string
  renderLabel?: ({ item, index, isSelected }: { item: Data; index: number; isSelected: boolean }) => ReactNode
  renderBrief?: ({ item, index, isSelected }: { item: Data; index: number; isSelected: boolean }) => ReactNode
  renderItem?: ({
    item,
    index,
    isSelected,
    onSelect,
  }: {
    item: Data
    index: number
    isSelected: boolean
    onSelect: () => void
  }) => ReactNode
  onClose?: () => void
  onConfirm?: (value: string, index: number, item: Data) => void
}

export const PopupSelect: FC<PopupSelectProps> = ({
  data,
  open,
  params,
  briefClass,
  labelClass,
  emptyExtra,
  title = '请选择',
  labelKey = 'label',
  valueKey = 'value',
  emptyText = '暂无数据',
  cancelText = '取消',
  confirmText = '确定',
  request,
  formatter,
  transform,
  renderItem,
  renderLabel,
  renderBrief,
  onClose,
  onConfirm,
}) => {
  const [current, setCurrent] = useState(0)

  const service = useCallback(async (): Promise<Data[]> => {
    if (request) {
      const res = await request(params)
      return transform ? transform(res) : res
    }
    return []
  }, [params, request, transform])

  const {
    data: items,
    loading,
    run,
  } = useRequest(service, {
    manual: true,
  })

  const columns = useMemo(() => items ?? data ?? [], [data, items])

  useEffect(() => {
    if (open && !columns.length) {
      run()
    }
  }, [open])

  const getLabel = useCallback(
    (item: Data, index: number) => {
      if (formatter) {
        return formatter(item, index)
      }
      return item[labelKey]
    },
    [formatter, labelKey]
  )

  const handleClick = useCallback(
    (index: number) => {
      if (columns[index]?.disabled) return

      setCurrent(index)
    },
    [columns]
  )

  const handleConfirm = useCallback(() => {
    const item = columns[current]
    if (!item) return onClose?.()

    onConfirm?.(item[valueKey], current, item)
    onClose?.()
  }, [columns, current, onClose, onConfirm, valueKey])

  return (
    <Popup open={open} placement="bottom" onClose={onClose}>
      <Navbar bordered>
        <Navbar.NavLeft icon={false} onClick={onClose}>
          {cancelText}
        </Navbar.NavLeft>
        <Navbar.Title>{title}</Navbar.Title>
        <Navbar.NavRight onClick={handleConfirm}>{confirmText}</Navbar.NavRight>
      </Navbar>
      <SafeArea className="relative" position="bottom">
        {isEmpty(columns) ? (
          loading ? (
            <View className="p-6 flex flex-center" style="min-height:264px">
              <Loading direction="vertical">
                <Text>加载中...</Text>
              </Loading>
            </View>
          ) : (
            <Empty style="min-height:264px">
              <Empty.Image />
              <Empty.Description>{emptyText}</Empty.Description>
              {emptyExtra}
            </Empty>
          )
        ) : (
          <ScrollView scrollY style="min-height:264px">
            {columns.map((item, index) =>
              renderItem ? (
                renderItem({ item, index, isSelected: current === index, onSelect: () => handleClick(index) })
              ) : (
                <Cell
                  key={index}
                  isLink
                  align="center"
                  clickable={!item.disabled}
                  titleClass={labelClass}
                  briefClass={briefClass}
                  title={
                    renderLabel ? renderLabel({ item, index, isSelected: current === index }) : getLabel(item, index)
                  }
                  brief={renderBrief ? renderBrief({ item, index, isSelected: current === index }) : null}
                  rightIcon={current === index ? <Icon name="checked" color="var(--color-primary)" size={24} /> : null}
                  onClick={() => handleClick(index)}
                />
              )
            )}
          </ScrollView>
        )}
      </SafeArea>
    </Popup>
  )
}

export default PopupSelect
